﻿using RAP.Framework.Libary.DataSource.Model;
using RAP.Framework.Libary.DomTemplateBuilder;
using RAP.Framework.Libary.SqlDataService.Service;
using RAP.Framework.Libary.Utils;
using RAP.Web.Libary.Common;
using RAP.Web.Libary.Common.Model;
using RAP.Web.Libary.Common.Model.Log;
using System;
using System.Collections;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using static RAP.Framework.Libary.DataSource.ServiceUtils;
using static RAP.Web.Libary.Common.FieldConsts;
using RAP.Framework.Libary.SqlDataService;
using RAP.Framework.Libary.DataSource.Context;
using RAP.Framework.Libary.DataSource;

namespace RAP.Web.Libary.Service
{
	/// <summary>
	/// 服务层基类
	/// </summary>
	public abstract class APIServiceBase : IAPIService, IDisposable
	{
		/// <summary>
		/// 
		/// </summary>
		protected virtual IServiceProvider ServiceProvider { get; set; }

		/// <summary>
		/// 数据服务对象
		/// </summary>
		public virtual ISqlDataService SqlDataService { get; set; }

		/// <summary>
		/// 名称空间
		/// </summary>
		public virtual string NameSpace
		{
			get
			{
				return GetType().FullName;
			}
		}

		/// <summary>
		/// 写入日志的SQL模板Id
		/// </summary>
		public virtual string WriteLogTemplateId { get; set; } = "RAP.Web.Core.Server.Service.Log.LogService.WriteLog";

		/// <summary>
		/// 
		/// </summary>
		public APIServiceBase( )
		{
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="serviceProvider"></param>
		public APIServiceBase( IServiceProvider serviceProvider )
		{
			ServiceProvider = serviceProvider;
			SqlDataService = serviceProvider.GetService<ISqlDataService>();
			SqlDataService.NameSpace = NameSpace;
			SqlDataService.OnEndExecute += SqlDataService_OnEndExecute;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="eventParam"></param>
		protected virtual void SqlDataService_OnEndExecute( SqlDataServiceEventArgs eventParam )
		{
			WriteTemplateLog( eventParam );
		}

		/// <summary>
		/// 返回错误结果
		/// </summary>
		/// <param name="errorMessage"></param>
		/// <param name="errorCode"></param>
		/// <returns></returns>
		protected virtual object ErrorContent( string errorMessage, int errorCode = int.MaxValue )
		{
			return ServiceResult.CreateErrorResult( errorMessage, errorCode );
		}

		/// <summary>
		/// 获取SQL模板的日志数据参数
		/// </summary>
		/// <param name="eventParam"></param>
		/// <returns></returns>
		protected virtual IQueryParams GetTemplateLogData( SqlDataServiceEventArgs eventParam )
		{
			var queryParma = eventParam.Param;
			var tpl = queryParma.TemplateId;
			var tplItem = DomTemplateManager.Instance.GetTemplateItem( tpl );
			if ( tplItem == null )
			{
				//应该记录一下这种非法调用
				return null;
			}
			var customerAttrs = tplItem.Attributes;
			if ( customerAttrs.Count == 0 )
			{
				//不需要记录日志
				return null;
			}
			var moduleName = customerAttrs.ModuleName();
			if ( moduleName.IsNullOrEmpty() )
			{
				//不需要记录日志
				return null;
			}
			var logParamNames = customerAttrs.ModuleParams();
			var logPrams = new ArrayList();
			//获取日志需要保存的参数
			if ( logParamNames.IsNotNullOrEmpty() )
			{
				foreach ( var name in logParamNames.Split( ',', StringSplitOptions.RemoveEmptyEntries ) )
				{
          var paramName = name.LeftEndString( AS_SYNTAX, name );//判断是否有 as 关键字，如果有则参数取别名
          object paramValue = null;
					int idxTag = -1;
					//判断参数是否是常量
					{
						idxTag = paramName.IndexOf( ':' );
						if ( idxTag < 0 )
						{
							paramValue = queryParma.GetValue( name );
						}
						else
						{
							string[] arrParams = paramName.Split( ':' );
							paramName = arrParams[ 0 ].Trim();
							paramValue = arrParams[ 1 ].Trim();
						}
					}
					if ( paramValue.IsNotNullOrEmpty() )
					{
						logPrams.Add( new Hashtable()
						{
							{
								"Name", paramName
							},
							{
								"Value", paramValue.ToString ( )
							}
						} );
					}
				}
			}
			dynamic logParams = queryParma;
			logParams.TemplateId = WriteLogTemplateId;
			logParams.ModuleId = tpl;
			logParams.ModuleName = moduleName;
			logParams.Params = logPrams;
			logParams.StartTime = eventParam.StartTime;
			logParams.Duration = eventParam.Duration;
			logParams.DataCount = eventParam.DataCount;
			
			return queryParma;
		}

		/// <summary>
		/// 写入SQL模板的日志
		/// </summary>
		/// <param name="eventParam"></param>
		protected virtual void WriteTemplateLog( SqlDataServiceEventArgs eventParam )
		{
			var logData = GetTemplateLogData( eventParam );
			if ( logData != null )
			{
				SqlDataService.ExecuteNonQuery( logData, nameof( WriteLog ), allowFireEvent: false );
			}
		}

		/// <summary>
		/// 写入一般日志
		/// </summary>
		/// <returns></returns>
		public virtual async Task WriteLog( IQueryParams queryParam )
		{
			var logParam = ServiceProvider.GetService<ILogParams>();
			logParam.TemplateId = WriteLogTemplateId;
			logParam.StartTime = DateTime.Now;
			queryParam.CopyTo( logParam );
			await SqlDataService.ExecuteNonQuery( logParam, allowFireEvent: false );
		}

		/// <summary>
		/// 
		/// </summary>
		public void Dispose( )
		{
			if ( this.SqlDataService != null )
			{
				this.SqlDataService.OnEndExecute -= SqlDataService_OnEndExecute;
			}

		}
	}
}
